package com.gateway.filter;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

import com.gateway.handler.HandleException;
import java.util.Map;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.data.id.IdUtil;
import org.dromara.hutool.core.text.AntPathMatcher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author xiangminwen
 * @date 2025/2/20 9:32
 */
@Component
public class CommonGlobalFilter implements GlobalFilter {

    public static final String TRACE_ID = "TRACE_ID";
    public static final String PERMIT_URL = "permit-url";
    public static final String IGNORES_URL = "ignores-url";
    AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getRequest().mutate().header(TRACE_ID, IdUtil.objectId());
        String path = exchange.getRequest().getURI().getPath();
        Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
        // 是否免登录
        if (hasIgnore(route, path)) {
            return chain.filter(exchange);
        }
        // 是有权限
        if (hasPermit(route, path)) {
            return chain.filter(exchange);
        }
        return HandleException.writeError(exchange, "301", "请登录");
    }

    private boolean hasIgnore(Route route, String path) {
        Map<String, String> ignoreMap = (Map<String, String>) route.getMetadata().get(IGNORES_URL);
        if (CollUtil.isNotEmpty(ignoreMap)) {
            return ignoreMap.values().stream().anyMatch(url -> pathMatcher.match(url, path));
        }
        return false;
    }

    private boolean hasPermit(Route route, String path) {
        Map<String, String> permitMap = (Map<String, String>) route.getMetadata().get(PERMIT_URL);
        if (CollUtil.isNotEmpty(permitMap)) {
            for (String url : permitMap.values()) {
                if (pathMatcher.match(url, path)) {
                    return true;
                }
            }
        }
        return true;
    }
}
